package com.lf.sys.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import org.apache.commons.lang3.StringUtils;

public class MailContent {
	private String messageId;// 消息id
	private int messageNumber;//
	private String bodyText;// 正文
	private Date sentDate;// 发件时间
	private String subject;// 主题
	private int size;// 邮件大小
	private String from;// 发件人
	private MimeMessage mimeMessage;//
	private InternetAddress[] mailAddress;// 收件人
	private InternetAddress[] copyTo;// 收件人
	private InternetAddress[] bCopyTo;// 收件人
	private boolean hasAttachMent;// 是否有附件
	private boolean isNew;// 是否新邮件
	private Message message;
	private int state;
	private String error;

	private ArrayList<String> fileNames;// 保存附件后会有内容

	public MailContent(Message message) {
		this.message = message;
		this.init();
	}

	private void init() {
		this.mimeMessage = (MimeMessage) this.message;
		this.fileNames = new ArrayList<String>();
		try {
			this.isNew = this.message.getFlags().contains(Flags.Flag.SEEN);
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "读取邮件是否已读标志失败：" + e.getMessage();
			e.printStackTrace();
		}
		try {
			this.hasAttachMent = this.isContainAttachment(mimeMessage);
			// System.out.println(this.hasAttachMent);
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "读取是否含有附件失败：" + e.getMessage();
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "读取是否含有附件io失败：" + e.getMessage();
			e.printStackTrace();
		}
	}

	/**
	 * 获取邮件内容
	 * 
	 * @param part
	 * @param content
	 * @throws MessagingException
	 * @throws IOException
	 */
	private void getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException {
		// 如果是文本类型的附件，通过getContent方法可以取到文本内容，但这不是我们需要的结果，所以在这里要做判断
		boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
		if (part.isMimeType("text/*") && !isContainTextAttach) {
			content.append(part.getContent().toString());
		} else if (part.isMimeType("message/rfc822")) {
			getMailTextContent((Part) part.getContent(), content);
		} else if (part.isMimeType("multipart/*")) {
			Multipart multipart = (Multipart) part.getContent();
			int partCount = multipart.getCount();
			BodyPart bodyPart=null;
			for (int i = 0; i < partCount; i++) {
				BodyPart temp = multipart.getBodyPart(i);
				if(temp.isMimeType("text/html")){
					bodyPart=temp;
					break;
				}
			}
			if(bodyPart!=null){
				getMailTextContent(bodyPart, content);
			}else{
				for (int i = 0; i < partCount; i++) {
					BodyPart temp = multipart.getBodyPart(i);
					getMailTextContent(temp, content);
				}
			}
		}
	}

	/**
	 * 获取收件人地址字符串,逗号隔开
	 * 
	 * @return
	 */
	public String getMailAddressStr() {
		if(this.getMailAddress()==null||this.getMailAddress().length<1){
			return "";
		}
		String[] temp = new String[this.getMailAddress().length];
		for (int i = 0; i < this.getMailAddress().length; i++) {
			temp[i] = this.getMailAddress()[i].getAddress();
		}
		if (temp == null || temp.length < 1) {
			return "";
		} else {
			return StringUtils.join(temp, ",");
		}
	}

	/**
	 * 获取抄送地址字符串,逗号隔开
	 * 
	 * @return
	 */
	public String getCopyToStr() {
		if(this.getCopyTo()==null||this.getCopyTo().length<1){
			return "";
		}
		String[] temp = new String[this.getCopyTo().length];
		for (int i = 0; i < this.getCopyTo().length; i++) {
			temp[i] = this.getCopyTo()[i].getAddress();
		}
		if (temp == null || temp.length < 1) {
			return "";
		} else {
			return StringUtils.join(temp, ",");
		}
	}

	/**
	 * 获取密送地址字符串,逗号隔开
	 * 
	 * @return
	 */
	public String getBCopyToStr() {
		if(this.getbCopyTo()==null||this.getbCopyTo().length<1){
			return "";
		}
		String[] temp = new String[this.getbCopyTo().length];
		for (int i = 0; i < this.getbCopyTo().length; i++) {
			temp[i] = this.getbCopyTo()[i].getAddress();
		}
		if (temp == null || temp.length < 1) {
			return "";
		} else {
			return StringUtils.join(temp, ",");
		}
	}

	/**
	 * 判断是否有附件
	 * 
	 * @param part
	 * @return
	 * @throws MessagingException
	 * @throws IOException
	 */
	private boolean isContainAttachment(Part part) throws MessagingException, IOException {
		boolean flag = false;
		if (part.isMimeType("multipart/*")) {
			MimeMultipart multipart = (MimeMultipart) part.getContent();
			int partCount = multipart.getCount();
			for (int i = 0; i < partCount; i++) {
				BodyPart bodyPart = multipart.getBodyPart(i);
				String disp = bodyPart.getDisposition();
				if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) {
					flag = true;
				} else if (bodyPart.isMimeType("multipart/*")) {
					flag = isContainAttachment(bodyPart);
				} else {
					String contentType = bodyPart.getContentType();
					if (contentType.indexOf("application") != -1) {
						flag = true;
					}
					if (contentType.indexOf("name") != -1) {
						flag = true;
					}
				}
				if (flag)
					break;
			}
		} else if (part.isMimeType("message/rfc822")) {
			flag = isContainAttachment((Part) part.getContent());
		}
		return flag;
	}

	/**
	 * 保存附件
	 * 
	 * @param destDir
	 */
	public void saveAttachment(String destDir) {
		try {
			this.saveAttachment(this.mimeMessage, destDir);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "不支持编码失败：" + e.getMessage();
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "找不到文件：" + e.getMessage();
			e.printStackTrace();
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "读取附件码失败：" + e.getMessage();
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			this.state = 3;
			this.error = "读取附件码io失败：" + e.getMessage();
			e.printStackTrace();
		}
	}

	/**
	 * 保存附件
	 * 
	 * @param part
	 * @param destDir
	 * @throws UnsupportedEncodingException
	 * @throws MessagingException
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void saveAttachment(Part part, String destDir)
			throws UnsupportedEncodingException, MessagingException, FileNotFoundException, IOException {
		if (part.isMimeType("multipart/*")) {
			Multipart multipart = (Multipart) part.getContent(); // 复杂体邮件
			// 复杂体邮件包含多个邮件体
			int partCount = multipart.getCount();
			for (int i = 0; i < partCount; i++) {
				// 获得复杂体邮件中其中一个邮件体
				BodyPart bodyPart = multipart.getBodyPart(i);
				// 某一个邮件体也有可能是由多个邮件体组成的复杂体
				String disp = bodyPart.getDisposition();
				if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) {
					InputStream is = bodyPart.getInputStream();
					
				} else if (bodyPart.isMimeType("multipart/*")) {
					saveAttachment(bodyPart, destDir);
				} 
			}
		} else if (part.isMimeType("message/rfc822")) {
			saveAttachment((Part) part.getContent(), destDir);
		}
	}



	/**
	 * 解码邮件内容
	 * 
	 * @param encodeText
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String decodeText(String encodeText) throws UnsupportedEncodingException {
		if (encodeText == null || "".equals(encodeText)) {
			return "";
		} else {
			return MimeUtility.decodeText(encodeText);
		}
	}

	public String getMessageId() {
		if (StringUtils.isBlank(this.messageId)) {
			try {
				this.messageId = this.mimeMessage.getMessageID();
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 1;
				this.error = "读取邮件id失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return messageId;
	}

	public void setMessageId(String messageId) {
		this.messageId = messageId;
	}

	public int getMessageNumber() {
		this.messageNumber = this.message.getMessageNumber();
		return messageNumber;
	}

	public void setMessageNumber(int messageNumber) {
		this.messageNumber = messageNumber;
	}

	public String getBodyText() {
		if (StringUtils.isBlank(this.bodyText)) {
			try {
				StringBuffer temp = new StringBuffer();
				this.getMailTextContent(mimeMessage, temp);
				this.bodyText = temp.toString();
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取内容失败：" + e.getMessage();
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取内容io失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return bodyText;
	}

	public void setBodyText(String bodyText) {
		this.bodyText = bodyText;
	}

	public Date getSentDate() {
		if (this.sentDate == null) {
			try {
				this.sentDate = this.message.getSentDate();
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取发送日期失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return sentDate;
	}

	public void setSentDate(Date sentDate) {
		this.sentDate = sentDate;
	}

	public String getSubject() {
		if (StringUtils.isBlank(this.subject)) {
			try {
				System.out.println(this.message.getSubject());
				this.subject = MimeUtility.decodeText(CommonUtils.getStringNoTrim(this.message.getSubject()));
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取主题时解码失败：" + e.getMessage();
				this.subject = "";
				e.printStackTrace();
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取主题失败：" + e.getMessage();
				this.subject = "";
				e.printStackTrace();
			}
		}
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public int getSize() {
		if (this.size < 1) {
			try {
				this.size = this.message.getSize();
			} catch (MessagingException e1) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取邮件大小错误：" + e1.getMessage();
				e1.printStackTrace();
			}
		}
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public String getFrom() {
		if (StringUtils.isBlank(this.from)) {
			try {
				this.from = ((InternetAddress) this.mimeMessage.getFrom()[0]).getAddress();
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取发送人失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return from;
	}

	public void setFrom(String from) {
		this.from = from;
	}

	public MimeMessage getMimeMessage() {
		return mimeMessage;
	}

	public void setMimeMessage(MimeMessage mimeMessage) {
		this.mimeMessage = mimeMessage;
	}

	public InternetAddress[] getMailAddress() {
		if (this.mailAddress == null || this.mailAddress.length < 1) {
			try {
				Address[] temp = this.mimeMessage.getRecipients(Message.RecipientType.TO);
				if (temp != null && temp.length > 0) {
					this.mailAddress = new InternetAddress[temp.length];
					for (int i = 0; i < temp.length; i++) {
						this.mailAddress[i] = (InternetAddress) temp[i];
					}
				}
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取邮件收件人失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return this.mailAddress;
	}

	public InternetAddress[] getCopyTo() {
		if (this.copyTo == null || this.copyTo.length < 1) {
			try {
				Address[] temp = this.mimeMessage.getRecipients(Message.RecipientType.CC);
				if (temp != null && temp.length > 0) {
					this.copyTo = new InternetAddress[temp.length];
					for (int i = 0; i < temp.length; i++) {
						this.copyTo[i] = (InternetAddress) temp[i];
					}
				}
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取邮件抄送失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return this.copyTo;
	}

	public InternetAddress[] getbCopyTo() {
		if (this.bCopyTo == null || this.bCopyTo.length < 1) {
			try {
				Address[] temp = this.mimeMessage.getRecipients(Message.RecipientType.BCC);
				if (temp != null && temp.length > 0) {
					this.bCopyTo = new InternetAddress[temp.length];
					for (int i = 0; i < temp.length; i++) {
						this.bCopyTo[i] = (InternetAddress) temp[i];
					}
				}
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				this.state = 3;
				this.error = "读取邮件密送失败：" + e.getMessage();
				e.printStackTrace();
			}
		}
		return this.bCopyTo;
	}

	public void setbCopyTo(InternetAddress[] bCopyTo) {
		this.bCopyTo = bCopyTo;
	}

	public void setCopyTo(InternetAddress[] copyTo) {
		this.copyTo = copyTo;
	}

	public void setMailAddress(InternetAddress[] mailAddress) {
		this.mailAddress = mailAddress;
	}

	public boolean isHasAttachMent() {
		return hasAttachMent;
	}

	public void setHasAttachMent(boolean hasAttachMent) {
		this.hasAttachMent = hasAttachMent;
	}

	public boolean isNew() {
		return isNew;
	}

	public void setNew(boolean isNew) {
		this.isNew = isNew;
	}

	public Message getMessage() {
		return message;
	}

	public void setMessage(Message message) {
		this.message = message;
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	public String getError() {
		return error;
	}

	public void setError(String error) {
		this.error = error;
	}

	public ArrayList<String> getFileNames() {
		return fileNames;
	}

	public void setFileNames(ArrayList<String> fileNames) {
		this.fileNames = fileNames;
	}

}
